<template>
	<!-- 我直接绘制最后一个点，就是一边取点一边绘制，不要存到数组里了 -->
	<SafeAreaNavBar>
		<NavBar :height="44" title="请签名" :isNavBarLeftShow="false"></NavBar>
	</SafeAreaNavBar>
	<SafeAreaContent :offsetBottom="44">
		<view
			class="container"
			:style="{
				height: `${canvasHeight}rpx`,
			}"
		>
			<view
				class="canvas_container"
				:style="{
					padding: `${canvasPadding}rpx`,
					height: `${canvasHeight}rpx`,
				}"
			>
				<!-- #ifdef MP-ALIPAY -->
				<canvas
					id="signCanvas"
					canvas-id="signCanvas"
					class="canvas"
					:style="{
						width: `${canvasWidth}rpx`,
						height: `${canvasHeight}rpx`,
					}"
					:disable-scroll="true"
					@touchstart="handleTouchStart"
					@touchmove="handleTouchMove"
					@touchend="handleTouchEnd"
				></canvas>
				<!-- #endif -->
				<!-- #ifndef MP-ALIPAY -->
				<canvas
					canvas-id="signCanvas"
					id="signCanvas"
					class="canvas"
					:style="{
						width: `${canvasWidth}rpx`,
						height: `${canvasHeight}rpx`,
					}"
					:disable-scroll="true"
					@touchstart="handleTouchStart"
					@touchmove="handleTouchMove"
					@touchend="handleTouchEnd"
				></canvas>
				<!-- #endif -->
			</view>

			<view class="controls">
				<button @click="undo" :disabled="!canUndo">撤销</button>
				<button @click="redo" :disabled="!canRedo">重做</button>
				<button @click="clearCanvas">清除</button>
				<button @click="saveImage">确定</button>
				<!-- <button @click="exportBase64">导出Base64</button> -->
			</view>
		</view>
	</SafeAreaContent>
</template>

<script>
export default {
	emits: ['onSaveImage'],
	data() {
		return {
			canvasId: 'signCanvas',
			color: '#000000',
			penWidth: 4,
			widths: [1, 2, 4, 6, 8],
			isDrawing: false,
			lastPoint: null,
			currentLine: null,
			lines: [], // 存储所有已完成的线条
			undoneLines: [], // 存储已撤销的线条（用于重做）
			ctx: null,
			canvasWidth: 750, // canvas宽度
			canvasHeight: 800, // canvas高度
			canvasDPRWidth: 0, // 屏幕分辨率 * canvas宽度
			canvasDPRHeight: 0, // 屏幕分辨率 * canvas高度
			canvasPadding: '0',
			dpr: 1,
			// timer: null, // 定时器
		};
	},
	computed: {
		canUndo() {
			// 当有线条可以撤销时返回true
			return this.lines.length > 0;
		},
		canRedo() {
			// 当有线条可以重做时返回true
			return this.undoneLines.length > 0;
		},
	},
	onReady() {
		this.initCanvas();
	},
	beforeDestroy() {
		this.clearCanvas();
	},
	methods: {
		initCanvas() {
			const that = this;

			// #ifdef MP-ALIPAY
			that.ctx = uni.createCanvasContext(`${'signCanvas'}`);
			// #endif
			// #ifndef MP-ALIPAY
			that.ctx = uni.createCanvasContext(`${'signCanvas'}`, that);
			// #endif
		},

		getTouchPoint(e) {
			const touch = e.touches ? e.touches[0] : e;
			let x = null;
			let y = null;
			// console.log('that.canvasRect:', this.ctx);
			// console.log('touch point111:', touch);
			// console.log('touch point222:', this.canvasRect);

			x = touch.x;
			y = touch.y;
			return { x, y };
		},

		handleTouchStart(e) {
			this.isDrawing = true;
			// 开始一条新线
			this.currentLine = [];
			// 将新线添加到线条数组中
			this.lines.push(this.currentLine);
			// 清空重做栈（开始新绘制操作后不能再重做）
			this.undoneLines = [];
			// 记录起始点
			this.lastPoint = this.getTouchPoint(e);
		},

		handleTouchMove(e) {
			if (!this.isDrawing) return;
			const point = this.getTouchPoint(e);
			const opt = {
				startX: this.lastPoint.x,
				startY: this.lastPoint.y,
				endX: point.x,
				endY: point.y,
				color: this.color,
				width: this.penWidth,
			};
			// 将线段添加到当前线中
			this.currentLine.push(opt);
			// 更新最后点位置
			this.lastPoint = point;
			// 直接绘制线段，不重绘整个画布
			this.drawLine(opt);
		},

		handleTouchEnd() {
			this.isDrawing = false;
			// 结束当前线绘制
			this.currentLine = null;
			// 确保绘制完成
			this.ctx.draw(true);
		},

		drawLine(line) {
			// console.log('line===', line);
			this.ctx.beginPath();
			this.ctx.moveTo(line.startX, line.startY);
			this.ctx.lineTo(line.endX, line.endY);

			// 设置颜色和宽度
			this.ctx.setStrokeStyle(line.color);
			this.ctx.setLineWidth(line.width || 2);
			// 设置线段样式，使线条更平滑
			this.ctx.setLineCap('round');
			this.ctx.setLineJoin('round');

			this.ctx.stroke();

			// 使用false参数避免清空之前的内容，实现增量绘制
			this.ctx.draw(true);
		},

		// 重绘所有线条（仅在撤销、重做、清除时使用）
		redrawAllLines() {
			if (!this.ctx) return;

			// 清空画布
			this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);

			// 重新绘制所有线条
			for (const lineGroup of this.lines) {
				for (const line of lineGroup) {
					this.ctx.beginPath();
					this.ctx.moveTo(line.startX, line.startY);
					this.ctx.lineTo(line.endX, line.endY);

					// 设置颜色和宽度
					this.ctx.setStrokeStyle(line.color);
					this.ctx.setLineWidth(line.width || 2);
					// 设置线段样式，使线条更平滑
					this.ctx.setLineCap('round');
					this.ctx.setLineJoin('round');

					this.ctx.stroke();
				}
			}

			// 提交绘制
			this.ctx.draw(true);
		},

		clearCanvas() {
			// 清空所有线条数据
			this.lines = [];
			this.undoneLines = [];
			this.currentLine = null;

			// 清空画布
			this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight);
			this.ctx.draw(true);
		},

		undo() {
			// 检查是否有可撤销的线条
			if (this.lines.length > 0) {
				// 将最后一条线移到重做栈中
				const lastLine = this.lines.pop();
				this.undoneLines.push(lastLine);
				// 重新绘制所有剩余线条
				this.redrawAllLines();
			}
		},

		redo() {
			// 检查是否有可重做的线条
			if (this.undoneLines.length > 0) {
				// 将最后撤销的线恢复到线条数组中
				const lineToRedo = this.undoneLines.pop();
				this.lines.push(lineToRedo);
				// 重新绘制所有线条
				this.redrawAllLines();
			}
		},

		saveImage() {
			const that = this;
			// 确保最新画面已绘制
			this.ctx.draw(true);

			// #ifdef MP-ALIPAY
			// 支付宝必须用原生 API + canvas 实例
			uni
				.createSelectorQuery()
				.select('#signCanvas')
				.node()
				.exec(res => {
					const canvas = res[0]?.node;

					my.canvasToTempFilePath({
						canvas, // 必须传 canvas 实例
						fileType: 'png',
						success: res => {
							uni.showToast({
								title: '保存成功',
								icon: 'success',
								duration: 1500,
							});
							console.log('支付宝图片路径:', res.tempFilePath);
							// this.$emit('onSaveImage', res.tempFilePath);
							that.$jump(
								'redirectTo',
								'/pages/agreement/agreement?tempFilePath=' + res.tempFilePath
							);
						},
						fail: err => {
							uni.showToast({
								title: '保存失败',
								icon: 'error',
								duration: 1500,
							});
							console.error('支付宝导出失败:', err);
						},
					});
				});
			// #endif

			// #ifndef MP-ALIPAY
			// 微信等平台使用 uni 封装
			uni.canvasToTempFilePath(
				{
					canvasId: 'signCanvas',
					fileType: 'png',
					success: res => {
						uni.showToast({
							title: '保存成功',
							icon: 'success',
							duration: 1500,
						});
						console.log('图片路径:', res.tempFilePath);
						// this.$emit('onSaveImage', res.tempFilePath);
						that.$jump(
							'redirectTo',
							'/pages/agreement/agreement?tempFilePath=' + res.tempFilePath
						);
					},
					fail: err => {
						uni.showToast({ title: '保存失败', icon: 'error', duration: 1500 });
						console.error('导出失败:', err);
					},
				},
				this // 微信需要传 this
			);
			// #endif
		},

		exportBase64() {
			// 确保最新画面已绘制
			this.ctx.draw(true);

			// #ifdef MP-ALIPAY
			uni
				.createSelectorQuery()
				.select('#signCanvas')
				.node()
				.exec(res => {
					const canvas = res[0]?.node;
					if (!canvas) {
						uni.showToast({
							title: 'Canvas 未就绪',
							icon: 'none',
							duration: 1500,
						});
						return;
					}

					my.canvasToTempFilePath({
						canvas, // 必须传 canvas 实例
						fileType: 'png',
						success: res => {
							// 使用支付宝的文件管理器读取文件并转为 base64
							if (my.getFileSystemManager) {
								const fs = my.getFileSystemManager();
								fs.readFile({
									filePath: res.tempFilePath,
									encoding: 'base64',
									success: fileRes => {
										const base64Data = 'data:image/png;base64,' + fileRes.data;
										my.setClipboardData({
											data: base64Data,
											success: () => {
												uni.showToast({
													title: 'Base64已复制',
													icon: 'none',
													duration: 1500,
												});
												console.log(base64Data);
											},
										});
									},
								});
							} else {
								uni.showToast({
									title: '当前平台不支持导出Base64',
									icon: 'none',
									duration: 1500,
								});
							}
						},
						fail: err => {
							uni.showToast({
								title: '导出失败',
								icon: 'error',
								duration: 1500,
							});
							console.error('支付宝导出Base64失败:', err);
						},
					});
				});
			// #endif

			// #ifndef MP-ALIPAY
			uni.canvasToTempFilePath(
				{
					canvasId: 'signCanvas',
					success: res => {
						if (uni.getFileSystemManager) {
							uni.getFileSystemManager().readFile({
								filePath: res.tempFilePath,
								encoding: 'base64',
								success: fileRes => {
									const base64Data = 'data:image/png;base64,' + fileRes.data;
									uni.setClipboardData({ data: base64Data });
									uni.showToast({
										title: 'Base64已复制',
										icon: 'none',
										duration: 1500,
									});
									console.log(base64Data);
								},
							});
						} else {
							uni.showToast({
								title: '当前平台不支持导出Base64',
								icon: 'none',
							});
						}
					},
					fail: err => {
						console.error('导出Base64失败', err);
					},
				},
				this // 微信需要传 this
			);
			// #endif
		},
	},
};
</script>

<style scoped>
.container {
	width: 100%;
	position: relative;
}

.canvas_container {
	width: 100%;
}

.canvas {
	width: 100%;
	background: #fff;
	border: 1px solid #ddd;
}

.controls {
	margin-top: 10px;
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	align-items: center;
	justify-content: center;
	padding: 10px;
}

button {
	padding: 8px 16px;
	border: 1px solid #007aff;
	background-color: #007aff;
	color: white;
	border-radius: 4px;
	font-size: 14px;
	cursor: pointer;
	outline: none;
}

button:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

button:hover:not(:disabled) {
	background-color: #0062cc;
	border-color: #0062cc;
}
</style>
